/*
 * A simple, awkward imitation to readelf
 * wonder how this file works, please see 'man 5 elf'
 */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <elf.h>

// static FILE *fp;
static int fd;
static struct stat st;
static uint8_t *elfmem;
static Elf64_Ehdr *ehdr;
static Elf64_Shdr *shdr;
static char *symtab;

int iself() {
  if (!strncmp((char *)ehdr->e_ident, ELFMAG, 4))
    return 1;
  else
    return 0;
}

int main(int argc, char *argv[])
{
  // get file description of specified file
  if ((fd = open(argv[1], O_RDONLY, 0)) < 0) {
    fprintf(stderr, "%s: can't open file %s\n", argv[0], argv[1]);
    exit(1);
  }

  fstat(fd, &st);

  elfmem = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if (elfmem == NULL) {
    fprintf(stderr, "%s: memory mapping failed\n", argv[0]);
    exit(1);
  }

  ehdr = (Elf64_Ehdr *)elfmem;
  if (!iself()) {
    fprintf(stderr, "%s: not a elf file [%s]\n", argv[0], argv[1]);
    exit(2);
  }

  printf("section header addr: 0x%lx\n", ehdr->e_shoff);

  shdr = (Elf64_Shdr *)&elfmem[ehdr->e_shoff];
  symtab = (char *)&elfmem[shdr[ehdr->e_shstrndx].sh_offset];

  printf("\nSection Headers:\n");
  printf("[Nr] Name\t\tType\tAddr\tOff\tSize\tES\tFlg\tLk\tInf\tAl\n");
  for (int i = 0; i < ehdr->e_shnum; i++) {
    if (shdr[i].sh_type == SHT_SYMTAB) {

    }
    printf("[%d] "
           "%s\t\t"
           "%u\t"
           "%lu\t"
           "%lu\t"
           "%lu\t"
           "%lu\t"
           "%lu\t"
           "%u\t"
           "%u\t"
           "%lu\n", i,
           &symtab[shdr[i].sh_name],
           shdr[i].sh_type,
           shdr[i].sh_addr,
           shdr[i].sh_offset,
           shdr[i].sh_size,
           shdr[i].sh_entsize,
           shdr[i].sh_flags,
           shdr[i].sh_link,
           shdr[i].sh_info,
           shdr[i].sh_addralign);
  }

  return EXIT_SUCCESS;
}
